﻿#include "Utils.h"
#include <nlohmann/json.hpp>
#include <boost/dll.hpp>
#include <sstream>

using namespace std;
using namespace fstr;
using json = nlohmann::json;
namespace bfs = boost::filesystem;

bfs::path Utils::getFullFilePath(const std::string& fileName,
	const std::string& subDir)
{
	bfs::path path(fileName);
	if (!path.is_absolute())
	{
		if (subDir.empty())
            path = boost::dll::program_location().parent_path() / path;
        else
			path = boost::dll::program_location().parent_path() / subDir / path;
	}
	return path;
}

bool Utils::getAndCheckFullFilePath(const std::string& fileName,
	const std::string& subDir, boost::filesystem::path& path, std::string& msg)
{
	path = getFullFilePath(fileName, subDir);

	if (!bfs::exists(path))
	{
        msg = "File not found: " + path.string();
        return false;
    }

	return true;
}

string Utils::genTmpFileStemByTime()
{
	time_t timep;
	time(&timep);
	char tmp[64];
	strftime(tmp, sizeof(tmp), "%Y-%m-%d_%H-%M-%S", localtime(&timep));
	return string(tmp);
}

bool Utils::genFullLogFileName(std::string& fileName, std::string& msg)
{
	fileName = genTmpFileStemByTime() + ".log";
	bfs::path filePath(fileName);
	if (filePath.is_absolute())
		return true;

	auto createLogFile = [&]() -> bool 
	{
        bfs::path outPath = boost::dll::program_location().parent_path() / "Logs";
        if (!bfs::exists(outPath))
            bfs::create_directories(outPath);
        filePath = outPath / filePath;
        fileName = filePath.string();
        return true;
    };

	return execWithEH(createLogFile, GENERATE_TAG(), msg);
}

bool Utils::execWithEH(const std::function<bool()>& code, 
	const std::string& tag, std::string& msg)
{
	try
	{
		return code(); // 执行传入的自定义代码
	}
	catch (const std::exception& e)
	{
		msg = tag + ": " + e.what();
	}
	catch (...)
	{
		msg = tag + ": Unknown exception";
	}

	return false; // 执行失败
}

string Utils::generateTag(const std::string& file,
	const std::string& function, int line)
{
	std::stringstream ss;
	ss << file << "::" << function << ":: " << line;
	return ss.str();
}

bool Utils::isIntersected(cv::Rect2d ra, cv::Rect2d rb)
{
	return (ra & rb).area() > 0;
}
